/*
 ============================================================================
 Name        : my_epoll.c
 Author      : liushen
 Version     :
 Copyright   : Your copyright notice
 Description : Hello World in C, Ansi-style
 ============================================================================
 */

#include "my_header.h"
#include "my_epoll.h"
#include "heartbeat_thread.h"
#include "my_math.h"

int my_debug_level = 0;
/****************************EPOLL DE*****************************/

enum epoll_cntl_op{
	EPOLL_CLOSE_HANDLE,
	EPOLL_CNTL_EVENTS
};

#define YOU_HANDLE(fd) (fd + 10000)
#define MY_HANDLE(fd) (fd - 10000)
#define MY_MAX_FD_LIMIT(max) (max + 20)

/***********************const**************************************/
#define MAX_BUFF_LEN 65000
#define MY_EPOLLET 0




/***********************inner func*********************************/
int setnonblocking(int sock)
{
	int opts;
	FUNC_START("sock = [%d]\n", sock);
	opts=fcntl(sock,F_GETFL);
	if(opts<0)
	{
		DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_ERROR, "[%d][%s]\n", errno, strerror(errno));
		FUNC_RETURN(-1);
	}
	opts = opts|O_NONBLOCK;
	if(fcntl(sock,F_SETFL,opts)<0)
	{
		DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_ERROR, "[%d][%s]\n", errno, strerror(errno));
		FUNC_RETURN(-2);
	}

	FUNC_RETURN(0);
}

int my_epoll_ctl(epoll_sock_t *p_epoll, int op,int events, int fd)
{
	struct epoll_event pt_ev;
	FUNC_START("epoll_sock_t *p_epoll = [%p], int op = [%d],int events = [%u], int fd = [%d]\n", p_epoll, op, events, fd);

	pt_ev.events = events;
	pt_ev.data.fd = fd;

	if(epoll_ctl(p_epoll->epoll_fd, op, fd, &pt_ev) < 0)
	{
	    DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_ERROR, "[%d][%s]\n", errno, strerror(errno));
	    DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_DEBUG, "p_epoll->cur_count = [%d]\n", p_epoll->cur_count);
	    FUNC_RETURN(-1);
	}

	if(op == EPOLL_CTL_ADD)
	{
		//p_epoll->start_handler(YOU_HANDLE(fd));
		update_my_conn_ested(1);
		p_epoll->cur_count ++;
	}

	if(op == EPOLL_CTL_DEL)
	{
		//p_epoll->end_handler(YOU_HANDLE(fd));
		update_my_conn_ested(-1);
		p_epoll->cur_count --;
		close(fd);
	}

	FUNC_RETURN(p_epoll->cur_count);
}

int init_epoll_sock(epoll_sock_t *p_my_epoll, epoll_args_t *args,
					my_start start_handler, my_read read_handler,
					my_write write_handler, my_end end_handler);
int exit_epoll_sock(epoll_sock_t *p_my_epoll);
int run_epoll_sock(epoll_args_t *args, epoll_sock_t *p_my_epoll);

/*****************************ext FUNCTION*************************/

int cntl_epoll_sock(epoll_sock_t *p_my_epoll, int you_handle, int epoll_cntl_op, int events);

inline int epoll_recv(int you_handle, char *data_buf, int buf_size)
{
	int ret = 0;
	int fd = MY_HANDLE(you_handle);
	FUNC_START("you_handle=[%d],my_handle = [%d], data_buf = [%p], buf_size = [%d]\n", you_handle, fd, data_buf, buf_size);
	ret = recv(fd, data_buf, buf_size, 0);
	FUNC_RETURN(ret);
}

inline int epoll_send(int you_handle, char *data_buf, int buf_len)
{
	int ret = 0;
	int fd = MY_HANDLE(you_handle);
	FUNC_START("you_handle=[%d],my_handle = [%d], data_buf = [%p], buf_len = [%d]\n", you_handle, fd, data_buf, buf_len);
	ret = send(fd, data_buf, buf_len, 0);
	FUNC_RETURN(ret);
}

int cntl_epoll_sock(epoll_sock_t *p_my_epoll, int you_handle, int epoll_cntl_op, int events)
{
	int epoll_ev = EPOLLIN | MY_EPOLLET | EPOLLRDHUP;

	if(epoll_cntl_op == EPOLL_OP_CLOSE)
	{
		return my_epoll_ctl(p_my_epoll, EPOLL_CTL_DEL, epoll_ev, MY_HANDLE(you_handle));
	}
	else if(epoll_cntl_op == EPOLL_OP_MODIFY)
	{
		if(events == EPOLL_EV_READ)
		{
			epoll_ev = EPOLLIN | MY_EPOLLET | EPOLLRDHUP;
		}
		else if(events == EPOLL_EV_WRITE)
		{
			epoll_ev = EPOLLOUT | MY_EPOLLET | EPOLLRDHUP;
		}
		else if(events == EPOLL_EV_RANDW)
		{
			epoll_ev = EPOLLIN | EPOLLOUT | MY_EPOLLET | EPOLLRDHUP;
		}
		else
		{
			return my_epoll_ctl(p_my_epoll, EPOLL_CTL_DEL, epoll_ev, MY_HANDLE(you_handle));
		}
		return my_epoll_ctl(p_my_epoll, EPOLL_CTL_MOD, epoll_ev, MY_HANDLE(you_handle));
	}
}

/*****************************ext FUNCTION*************************/

int init_epoll_sock(epoll_sock_t *p_my_epoll, epoll_args_t *args,
					my_start start_handler, my_read read_handler,
					my_write write_handler, my_end end_handler)
{
	int ret = 0;
	struct rlimit rt;
	int listener = 0;

	int i = 0, j = 0;
//	struct sockaddr_in my_addr, their_addr;
//	struct epoll_event tp_ev;
	base_func_t base_func = {(void*)p_my_epoll, cntl_epoll_sock, epoll_recv, epoll_send, ""};
	FUNC_START("p_my_epoll = [%p], max_sock = [%d], working_type = [%d],listen_port = [%d], listen_num = [%d], addr = [%s],conn_port = [%d], start_handler = [%p],read_handler = [%p], write_handler = [%p], end_handler = [%p]\n",
			p_my_epoll, args->max_sock, args->working_type, args->listen_port, args->listen_num, args->conn_addr, args->conn_port,
			   start_handler, read_handler, write_handler, end_handler);

	memset(p_my_epoll, 0x00, sizeof(epoll_sock_t));

	//alloc memmory
	p_my_epoll->pevents = calloc(args->max_sock, sizeof(struct epoll_event));
	if(NULL == p_my_epoll->pevents)
	{
		DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_ERROR, "[%d][%s]\n", errno, strerror(errno));
		p_my_epoll->init_state = -1;
		FUNC_RETURN(-1);
	}

	//set value
	p_my_epoll->max_size = args->max_sock;
	p_my_epoll->working_type = args->working_type;

	if(init_share_lib(p_my_epoll, args->conf_file, &base_func) != 0)
	{
		p_my_epoll->start_handler = start_handler;
		p_my_epoll->read_handler = read_handler;
		p_my_epoll->write_handler = write_handler;
		p_my_epoll->end_handler = end_handler;
		p_my_epoll->init_handler = NULL;
		p_my_epoll->exit_handler = NULL;
	}
	else
	{
		if(p_my_epoll->init_handler(&base_func) != 0)
		{
	        DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_ERROR, "[%d][%s]\n", errno, strerror(errno));
			p_my_epoll->init_state = -12;
	        FUNC_RETURN(-12);
		}
	}
    //set max fd limit
    rt.rlim_max = rt.rlim_cur = MY_MAX_FD_LIMIT(args->max_sock);
    if (setrlimit(RLIMIT_NOFILE, &rt) == -1)
	{
        DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_ERROR, "[%d][%s]\n", errno, strerror(errno));
		p_my_epoll->init_state = -2;
        FUNC_RETURN(-2);
    }

	//create epoll fd
	p_my_epoll->epoll_fd = epoll_create(args->max_sock);

	if(args->working_type)
	{
		DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_INFO, "run as server\n", errno, strerror(errno));

		//create listen socket
		if((listener = socket(PF_INET, SOCK_STREAM, 0)) == -1)
		{
		    DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_ERROR, "[%d][%s]\n", errno, strerror(errno));
			p_my_epoll->init_state = -3;
		    FUNC_RETURN(-3);
		}
		p_my_epoll->listen_fd = listener;

		//set non-block
		setnonblocking(listener);

		//set addr
		p_my_epoll->servaddr.sin_family = PF_INET;
		p_my_epoll->servaddr.sin_port = htons(args->listen_port);
		p_my_epoll->servaddr.sin_addr.s_addr = INADDR_ANY;

		//bind
		if (bind(listener, (struct sockaddr *) &p_my_epoll->servaddr, sizeof(struct sockaddr)) == -1)
		{
		    DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_ERROR, "[%d][%s]\n", errno, strerror(errno));
			close(listener);
			p_my_epoll->init_state = -4;
		    FUNC_RETURN(-4);
		}

		//listen
		if (listen(listener, args->listen_num) == -1)
		{
		    DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_ERROR, "[%d][%s]\n", errno, strerror(errno));
			close(listener);
			p_my_epoll->init_state = -5;
		    FUNC_RETURN(-5);

		}

		//add listen socket into epoll array
		if(my_epoll_ctl(p_my_epoll, EPOLL_CTL_ADD, EPOLLIN | MY_EPOLLET | EPOLLRDHUP, listener) < 0)
		{
		    DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_ERROR, "[%d][%s]\n", errno, strerror(errno));
			close(listener);
			p_my_epoll->init_state = -6;
		    FUNC_RETURN(-6);
		}
	}
	else
	{
		DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_INFO, "run as client\n", errno, strerror(errno));

		//set addr
		p_my_epoll->servaddr.sin_family = PF_INET;
		p_my_epoll->servaddr.sin_port = htons(args->conn_port);
		inet_aton(args->conn_addr, &p_my_epoll->servaddr.sin_addr);

	}

	p_my_epoll->init_state = 0;
	FUNC_RETURN(0);
}

int exit_epoll_sock(epoll_sock_t *p_my_epoll)
{
	FUNC_START("p_my_epoll = [%p]\n", p_my_epoll);
	exit_share_lib(p_my_epoll);
	if(p_my_epoll->pevents)
	{
		free(p_my_epoll->pevents);
	}
	FUNC_RETURN(0);
}


int reconn_client(epoll_sock_t *p_my_epoll, int conn_count)
{
	int i,ret;
	int cli_fd = 0;

	for(i = 0; i < conn_count; i ++)
	{
		//create socket
		cli_fd = socket(PF_INET, SOCK_STREAM, 0);
		if(cli_fd < 0)
		{
			DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_ERROR, "[%d][%s]\n", errno, strerror(errno));
			continue;
		}

		DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_INFO, "%d\n", j);

		//set non-block
		setnonblocking(cli_fd);

		//connect to server
		usleep(200);
		ret = connect(cli_fd, (struct sockaddr *)&p_my_epoll->servaddr, sizeof(struct sockaddr));
		DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_DEBUG, "CONN RET [%d]%s\n", errno, strerror(errno));
		if(ret < 0 && errno != EINPROGRESS)
		{
			DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_ERROR, "[%d]%s\n", errno, strerror(errno));
			close(cli_fd);
			continue;
		}
		else
		{
			if(ret == 0)
			{
				DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_INFO, "[%d]connect successed\n", cli_fd);
				if(my_epoll_ctl(p_my_epoll, EPOLL_CTL_ADD, EPOLLIN | MY_EPOLLET | EPOLLRDHUP, cli_fd) < 0)
				{
					DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_ERROR, "[%d][%s]\n", errno, strerror(errno));
					p_my_epoll->init_state = -7;
					FUNC_RETURN(-7);
				}

			}
			else
			{
				DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_INFO, "[%d]connect processing\n", cli_fd);
				if(my_epoll_ctl(p_my_epoll, EPOLL_CTL_ADD, EPOLLIN | EPOLLOUT | MY_EPOLLET | EPOLLRDHUP, cli_fd) < 0)
				{
					DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_ERROR, "[%d][%s]\n", errno, strerror(errno));
					p_my_epoll->init_state = -7;
					FUNC_RETURN(-7);
				}
			}
			//update_my_conn_ested(1);
			p_my_epoll->start_handler(YOU_HANDLE(cli_fd));
			//add client socket into epoll array
		}
	}
	FUNC_RETURN(0);
}

extern unsigned long my_conn_ested;

int run_client(epoll_args_t *args, epoll_sock_t *p_my_epoll)
{
	int ret = 0;
	int nfds = 0;
	int new_fd = 0;
	int n = 0;
	int cur_fd = 0;
	int opt_err = 0;
	int addrlen = 0;
	int optlen = 0;
	int free_conn_count = 0;
	char *p_buff = NULL;
	char *buff_len = 0;


	struct sockaddr_in their_addr;

	FUNC_START("p_my_epoll = [%p]\n", p_my_epoll);

	ret = reconn_client(p_my_epoll, args->max_sock);

	while(!p_my_epoll->init_state || p_my_epoll->cur_count <= 0)
	{
		//poll wait no timeout
		DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_DEBUG, "before epoll p_my_epoll->cur_count = [%d]\n", p_my_epoll->cur_count);
		nfds = epoll_wait(p_my_epoll->epoll_fd, p_my_epoll->pevents, p_my_epoll->cur_count, 1000);
		if (nfds == -1)
		{
		    DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_ERROR, "[%d][%s]\n", errno, strerror(errno));
		    break;
		}

		DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_DEBUG, "nfds = [%d]\n", nfds);

		//process events
		for (n = 0; n < nfds; ++n)
		{
			DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_DEBUG, "events[n].data.fd = [%d]\n", p_my_epoll->pevents[n].data.fd);
			DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_DEBUG, "events[n].events = [%u], EPOLLIN = [%u],  EPOLLOUT = [%u], EPOLLET = [%u], EPOLLRDHUP = [%u]\n", p_my_epoll->pevents[n].events, EPOLLIN, EPOLLOUT, EPOLLET, EPOLLRDHUP);
			cur_fd = p_my_epoll->pevents[n].data.fd;

			if(p_my_epoll->pevents[n].events & (EPOLLHUP | EPOLLERR))
			{
				//EPOLLERR
				if(!p_my_epoll->working_type)
				{
					DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_ERROR, "connect failed[%d][%s]\n", errno, strerror(errno));
					//update_my_conn_ested(-1);
					if(args->max_sock - p_my_epoll->cur_count >= args->per_con_num)
					{
						ret = reconn_client(p_my_epoll, args->max_sock - p_my_epoll->cur_count);
					}
				}

				ret = 0;
			}
			else
			{
				if(getsockopt(cur_fd, SOL_SOCKET, SO_ERROR, &opt_err, &optlen) < 0)
				{
					DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_ERROR, "[%d][%s]\n", errno, strerror(errno));
					p_my_epoll->init_state = -8;
					FUNC_RETURN(-8);
				}
				if(opt_err == 0)
				{
					DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_DEBUG, "sock status is ok\n");
					//no error write
					if(p_my_epoll->pevents[n].events & EPOLLIN)
					{
						ret = p_my_epoll->read_handler(YOU_HANDLE(cur_fd));
						if(ret > 0)
						{
							update_my_recv_bytes(ret);
						}
					}
					if(p_my_epoll->pevents[n].events & EPOLLOUT)
					{
						ret = p_my_epoll->write_handler(YOU_HANDLE(cur_fd));
						if(ret > 0)
						{
							update_my_send_bytes(ret);
						}
					}
				}
				else
				{
					DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_ERROR, "connect failed[%d][%s]\n", errno, strerror(errno));
					//update_my_conn_ested(-1);
					if(args->max_sock - p_my_epoll->cur_count >= 10)
					{
						ret = reconn_client(p_my_epoll, args->max_sock - p_my_epoll->cur_count);
					}
					ret = 0;
				}
			}

			if(ret == 0 || p_my_epoll->pevents[n].events & EPOLLRDHUP)
			{
				//EPOLLRDHUP closed by peer (2.6.17 or later)
//					if(my_epoll_ctl(p_my_epoll, EPOLL_CTL_DEL, EPOLLIN | MY_EPOLLET | EPOLLRDHUP, cur_fd) < 0)
//					{
//						DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_ERROR, "[%d][%s]\n", errno, strerror(errno));
//						close(new_fd);
//						p_my_epoll->init_state = -10;
//						FUNC_RETURN(-10);
//					}
				ret = p_my_epoll->end_handler(YOU_HANDLE(cur_fd));
			}

		    bzero(&p_my_epoll->pevents[n], sizeof(struct epoll_event));
		}
		print_my_counter(MY_COUNTER_ALL);
	}
	FUNC_RETURN(p_my_epoll->init_state);
}

int run_server(epoll_args_t *args, epoll_sock_t *p_my_epoll)
{
	int ret = 0;
	int nfds = 0;
	int new_fd = 0;
	int n = 0;
	int cur_fd = 0;
	int opt_err = 0;
	int addrlen = 0;
	int optlen = 0;
	char *p_buff = NULL;
	char *buff_len = 0;

	struct sockaddr_in their_addr;

	FUNC_START("p_my_epoll = [%p]\n", p_my_epoll);
	while(!p_my_epoll->init_state || p_my_epoll->cur_count <= 0)
	{
		//poll wait no timeout
		DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_DEBUG, "before epoll p_my_epoll->cur_count = [%d]\n", p_my_epoll->cur_count);
		nfds = epoll_wait(p_my_epoll->epoll_fd, p_my_epoll->pevents, p_my_epoll->cur_count, 500);
		if (nfds == -1)
		{
		    DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_ERROR, "[%d][%s]\n", errno, strerror(errno));
		    break;
		}
//		else if(nfds == 0)
//		{
//			new_fd = accept(cur_fd, (struct sockaddr *) &their_addr, &addrlen);
//
//			if (new_fd > 0)
//			{
//				//update_my_conn_ested(1);
//			}
//		}
		else
		{
			DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_DEBUG, "nfds = [%d]\n", nfds);
			//process events
			for (n = 0; n < nfds; ++n)
			{
				DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_DEBUG, "events[n].data.fd = [%d]\n", p_my_epoll->pevents[n].data.fd);
				DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_DEBUG, "events[n].events = [%u], EPOLLIN = [%u],  EPOLLOUT = [%u], EPOLLET = [%u], EPOLLRDHUP = [%u]\n", p_my_epoll->pevents[n].events, EPOLLIN, EPOLLOUT, EPOLLET, EPOLLRDHUP);
				cur_fd = p_my_epoll->pevents[n].data.fd;

				if (cur_fd == p_my_epoll->listen_fd)
				{
					//accept
					do{
						new_fd = accept(cur_fd, (struct sockaddr *) &their_addr, &addrlen);

						if (new_fd < 0)
						{
							DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_ERROR, "[%d][%s]\n", errno, strerror(errno));
							//bzero(&p_my_epoll->pevents[n], sizeof(struct epoll_event));
							//continue;
							if(errno == EAGAIN || errno == EWOULDBLOCK)
							{
								break;
							}
							else
							{
								return(-15);
							}
						}
						else
						{
							//update_my_conn_ested(1);
							DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_DEBUG, "source addr is %s:%d new socket is:%d", inet_ntoa(their_addr.sin_addr), ntohs(their_addr.sin_port), new_fd);
						}


						//set non-block
						setnonblocking(new_fd);

						//add client socket into epoll array
						if(my_epoll_ctl(p_my_epoll, EPOLL_CTL_ADD, EPOLLIN | MY_EPOLLET | EPOLLRDHUP, new_fd) < 0)
						{
							DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_ERROR, "[%d][%s]\n", errno, strerror(errno));
							close(new_fd);
							p_my_epoll->init_state = -7;
							FUNC_RETURN(-7);
						}
						ret = p_my_epoll->start_handler(YOU_HANDLE(new_fd));

					}while(1);
				}
				else
				{
					if(p_my_epoll->pevents[n].events & (EPOLLHUP | EPOLLERR))
					{
						//EPOLLERR
						if(!p_my_epoll->working_type)
						{
							DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_ERROR, "connect failed[%d][%s]\n", errno, strerror(errno));
							//update_my_conn_ested(-1);
						}

						ret = 0;
					}
					else
					{
						if(getsockopt(cur_fd, SOL_SOCKET, SO_ERROR, &opt_err, &optlen) < 0)
						{
							DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_ERROR, "[%d][%s]\n", errno, strerror(errno));
							p_my_epoll->init_state = -8;
							FUNC_RETURN(-8);
						}
						if(opt_err == 0)
						{
							DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_DEBUG, "sock status is ok\n");
							//no error write
							if(p_my_epoll->pevents[n].events & EPOLLIN)
							{
								ret = p_my_epoll->read_handler(YOU_HANDLE(cur_fd));
								if(ret > 0)
								{
									update_my_recv_bytes(ret);
								}
							}
							if(p_my_epoll->pevents[n].events & EPOLLOUT)
							{
								ret = p_my_epoll->write_handler(YOU_HANDLE(cur_fd));
								if(ret > 0)
								{
									update_my_send_bytes(ret);
								}
							}
						}
						else
						{
							DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_ERROR, "connect failed[%d][%s]\n", errno, strerror(errno));
							//update_my_conn_ested(-1);
							ret = 0;
						}
					}

					if(ret == 0 || p_my_epoll->pevents[n].events & EPOLLRDHUP)
					{
						//EPOLLRDHUP closed by peer (2.6.17 or later)
	//					if(my_epoll_ctl(p_my_epoll, EPOLL_CTL_DEL, EPOLLIN | MY_EPOLLET | EPOLLRDHUP, cur_fd) < 0)
	//					{
	//						DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_ERROR, "[%d][%s]\n", errno, strerror(errno));
	//						close(new_fd);
	//						p_my_epoll->init_state = -10;
	//						FUNC_RETURN(-10);
	//					}
						ret = p_my_epoll->end_handler(YOU_HANDLE(cur_fd));
					}

				}
				bzero(&p_my_epoll->pevents[n], sizeof(struct epoll_event));
			}
		}
		print_my_counter(MY_COUNTER_ALL);
	}
	FUNC_RETURN(p_my_epoll->init_state);
}

int run_epoll_sock(epoll_args_t *args, epoll_sock_t *p_my_epoll)
{
	if(p_my_epoll->working_type){
		FUNC_RETURN(run_server(args, p_my_epoll));
	}
	else{
		FUNC_RETURN(run_client(args, p_my_epoll));
	}

}

#define __MAIN__
#ifdef __MAIN__
int mmy_start(int handle)
{
	FUNC_START("handle = [%d]\n", handle);
	FUNC_RETURN(0);
}

int mmy_read(int handle)
{
	char data_buf[65535];
	int ret = 0;

	FUNC_START("handle = [%d]\n", handle);

	memset(data_buf, 0x00, sizeof(data_buf));
	ret = epoll_recv(handle, data_buf, sizeof(data_buf) - 1);

	FUNC_RETURN(ret);
}

int mmy_write(int handle)
{
	char data_buf[65535];
	int ret = 0;

	FUNC_START("handle = [%d]\n", handle);

	memset(data_buf, '1', sizeof(data_buf) - 1);
	data_buf[sizeof(data_buf) - 1] = '\0';
	ret = epoll_send(handle, data_buf, sizeof(data_buf) - 1);

	FUNC_RETURN(ret);
}

int mmy_end(int handle)
{
	FUNC_START("handle = [%d]\n", handle);
	FUNC_RETURN(0);
}

int main(int argc, char **argv)
{
#if 0
	notice_args_t p_args;
	int ret = init_notice_args(&p_args, 1000000, 100000);

	ret = init_heartbeat_thread(&p_args);
	sleep(10);
	ret = exit_heartbeat_thread(&p_args);
	return 0;
#else

	int ret = 0;
	epoll_args_t args = {};
	epoll_sock_t my_epoll;

	FUNC_START("argc = [%d]\n", argc);

	if (9 != argc && 11 != argc) {
		printf("Usage: working_type max_sock listen_port listen_num conn_addr conn_port conf_file debug_level interval per_con_num\n");
		printf("Server Example: 1 20000 6000 30 null 0 server_plugins.conf 0\n");
		printf("Client Example: 0 20000 0 0 127.0.0.1 6000 client_plugins.conf 0 1 2000\n");
		FUNC_RETURN(1);
	}

	args.working_type = atoi(argv[1]);
	args.max_sock = atoi(argv[2]);
	args.listen_port = atoi(argv[3]);
	args.listen_num = atoi(argv[4]);
	args.conn_addr = argv[5];
	args.conn_port = atoi(argv[6]);
	args.conf_file = argv[7];
	my_debug_level = atoi(argv[8]);

	if(!args.working_type)
	{
		args.interval = atoi(argv[9]);
		args.per_con_num = atoi(argv[10]);
	}

	ret = init_epoll_sock(&my_epoll, &args, (my_start)mmy_start, (my_read)mmy_read, (my_write)mmy_write, (my_end)mmy_end);

	ret = run_epoll_sock(&args, &my_epoll);

	ret = exit_epoll_sock(&my_epoll);

	FUNC_RETURN(0);
#endif
}
#endif
